import libc
import crypto.utils


type md5_t = struct{
    utils.mbedtls_md_context_t mbed_ctx
}

fn new():ptr<md5_t> {
    var m =  new md5_t()
    utils.mbedtls_md5_init(&m.mbed_ctx)
    //     MBEDTLS_MD_MD5=0x03,       /**< The MD5 message digest. */
    anyptr md_info = utils.mbedtls_md_info_from_type(0x03)
    assert(md_info > 0)

    utils.mbedtls_md_setup(&m.mbed_ctx, md_info, 0);

    utils.mbedtls_md_starts(&m.mbed_ctx);

    return m
}

fn md5_t.update([u8] input):ptr<md5_t> {
    utils.mbedtls_md_update(&self.mbed_ctx, (input as string).to_cstr(), input.len());

    return self
}

fn md5_t.finish():[u8] {
    var output = vec_new<u8>(0, 16) 
    utils.mbedtls_md_finish(&self.mbed_ctx, output.ref())

    utils.mbedtls_md_free(&self.mbed_ctx);

    return output
}

fn md5_t.hex():string {
    var output = vec_new<u8>(0, 16) 
    utils.mbedtls_md_finish(&self.mbed_ctx, output.ref())
    utils.mbedtls_md_free(&self.mbed_ctx);

    var result = utils.to_hex(output)
    return result
}

fn hex(string input):string {
    return new().update(input as [u8]).hex()
}